/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wangsan.study;

import org.springframework.context.annotation.Bean;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;

import com.wangsan.study.security.CustomUserDetailsService;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    //	@Autowired
    //	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    //		auth.inMemoryAuthentication()
    //			.withUser("user").password("password").roles("USER")
    //			.and()
    //			.withUser("test").password("test").roles("test")
    //		;
    //	}

    @Bean(name = "customUserDetailsService")
    @Override
    protected UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().mvcMatchers("/resources/**", "/error/**", "/static/**", "/favicon.ico", "/api/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
        //                eiuRegistry = http.authorizeRequests();
        //        List<Pair<String, String>> ruleList = new ArrayList<>();
        //        ruleList.add(Pair.of("/test", "hasRole('ROLE_Test')"));
        //        ruleList.add(Pair.of("/message/*", "hasRole('ROLE_Admin')"));
        //        ruleList.add(Pair.of("/test", "hasRole('ROLE_Admin')"));
        //
        //        final Map<String, Set<String>> ruleMap =
        //                ruleList.stream().collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping
        // (Pair::getSecond,
        //                        Collectors.toSet())));
        //
        //        ruleMap.entrySet().stream()
        //                .collect(Collectors
        //                        .toMap(e -> e.getKey(), e -> e.getValue().stream().collect(Collectors.joining(" or
        // "))))
        //                .forEach((k, v) -> eiuRegistry.mvcMatchers(k).access(v));
        //        eiuRegistry.anyRequest().authenticated();
        //
        //        http.csrf().disable()
        //                .formLogin().loginPage("/login")
        //                .and()
        //                .logout().permitAll();

        // ~~~~~~~~~~~~~~~~~~~

        http.csrf().disable()
                .formLogin().loginPage("/login").and().logout();

        final UrlAuthorizationConfigurer<HttpSecurity> urlAuthorizationConfigurer =
                new UrlAuthorizationConfigurer<>(getApplicationContext());
        http.apply((SecurityConfigurerAdapter) urlAuthorizationConfigurer);

        urlAuthorizationConfigurer
                .getRegistry()
                .antMatchers("/login", "/logout").access(AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY)
                .antMatchers("/test").access("ROLE_Test")
                .anyRequest().access(AuthenticatedVoter.IS_AUTHENTICATED_FULLY);

    }
}
